package com.gexiaobao.pigeon.ui.fragment.mine.banking

import android.annotation.SuppressLint
import android.graphics.BitmapFactory
import android.os.Bundle
import android.view.View
import androidx.lifecycle.lifecycleScope
import com.blankj.utilcode.util.ThreadUtils.runOnUiThread
import com.gexiaobao.pigeon.R
import com.gexiaobao.pigeon.app.base.BaseFragment
import com.gexiaobao.pigeon.app.eventViewModel
import com.gexiaobao.pigeon.app.ext.Constant
import com.gexiaobao.pigeon.app.ext.countDownCoroutines
import com.gexiaobao.pigeon.app.ext.init
import com.gexiaobao.pigeon.app.ext.initClose
import com.gexiaobao.pigeon.app.ext.showMessage
import com.gexiaobao.pigeon.app.model.bean.AccountUserInfo
import com.gexiaobao.pigeon.app.model.param.AccountBindPhoneBean
import com.gexiaobao.pigeon.app.model.param.AccountBindPhoneParam
import com.gexiaobao.pigeon.app.model.param.AccountRealNameParams
import com.gexiaobao.pigeon.app.model.param.ApplyBindCardParam
import com.gexiaobao.pigeon.app.model.param.SureBindCardParam
import com.gexiaobao.pigeon.app.rxui.tablayout.listener.GlideEngine
import com.gexiaobao.pigeon.app.util.Base64Util
import com.gexiaobao.pigeon.app.util.DatetimeUtil
import com.gexiaobao.pigeon.app.util.FileUtil
import com.gexiaobao.pigeon.app.util.MeSandboxFileEngine
import com.gexiaobao.pigeon.app.util.PictureUtil
import com.gexiaobao.pigeon.app.util.RxToast
import com.gexiaobao.pigeon.app.util.Util
import com.gexiaobao.pigeon.databinding.FragmentAccountSettingProcessBinding
import com.gexiaobao.pigeon.viewmodel.MineBankingViewModel
import com.luck.picture.lib.basic.PictureSelectionModel
import com.luck.picture.lib.basic.PictureSelector
import com.luck.picture.lib.config.SelectMimeType
import com.luck.picture.lib.config.SelectModeConfig
import com.luck.picture.lib.entity.LocalMedia
import com.luck.picture.lib.interfaces.OnResultCallbackListener
import com.luck.picture.lib.language.LanguageConfig
import com.luck.picture.lib.style.PictureSelectorStyle
import com.zs.easy.imgcompress.EasyImgCompress
import com.zs.easy.imgcompress.listener.OnCompressSinglePicListener
import com.zs.easy.imgcompress.util.GBMBKBUtil
import me.hgj.jetpackmvvm.ext.nav
import me.hgj.jetpackmvvm.ext.navigateAction
import me.hgj.jetpackmvvm.ext.parseState
import me.hgj.jetpackmvvm.ext.util.setOnclickNoRepeat
import me.hgj.jetpackmvvm.util.LogUtils
import okhttp3.MediaType
import okhttp3.MediaType.Companion.toMediaTypeOrNull
import okhttp3.OkHttpClient
import okhttp3.Request
import okhttp3.RequestBody
import okhttp3.RequestBody.Companion.toRequestBody
import org.json.JSONObject
import java.io.File
import java.io.IOException
import java.net.URLEncoder

/**
 * @Author      : hxw
 * @Date        : 2023/5/31 15:21
 * @Describe    : 账户设置流程
 */
class FragmentAccountSettingProcess : BaseFragment<MineBankingViewModel, FragmentAccountSettingProcessBinding>() {

    private var mTranceNum: String = ""
    private var mInToType: String = ""

    private var idCardFrontFile: File? = null
    private var idCardBackFile: File? = null
    private var mIdCardType: String = ""
    private val HTTP_CLIENT = OkHttpClient().newBuilder().build()
    private var idCardNumberTypeFront = 0
    private var idCardNumberTypeBack = 0

    override fun initView(savedInstanceState: Bundle?) {
        mInToType = arguments?.getString(Constant.INTO_TYPE).toString()
        if (mInToType == "mineBank") {
            mDatabind.includeToolbarMenu.tvRightMenu.visibility = View.GONE
        } else {
            mDatabind.includeToolbarMenu.tvRightMenu.visibility = View.VISIBLE
        }
        mDatabind.includeToolbarMenu.toolbar.initClose("账户设置流程") {
            nav().navigateUp()
        }
        mDatabind.includeToolbarMenu.tvRightMenu.text = "跳过"
        mDatabind.swipeRefreshView.init {
            mViewModel.getUserMemberInfo()
        }
    }

    override fun onResume() {
        super.onResume()
        mViewModel.getUserMemberInfo()
    }

    @SuppressLint("SetTextI18n")
    override fun createObserver() {
        super.createObserver()
        mViewModel.accountUserInfoResult.observe(viewLifecycleOwner) { resultState ->
            parseState(resultState, {
                if (mDatabind.swipeRefreshView.isRefreshing) {
                    mDatabind.swipeRefreshView.isRefreshing = false
                }
                mDatabind.data = it
                changeBtnStatus(it)
            })
        }

        mViewModel.realNameResult.observe(viewLifecycleOwner) {
            dismissLoading()
            if (it.isSuccess) {
                eventViewModel.toNoticeIsCertified.value = true
                mViewModel.getUserMemberInfo()
            } else {
                RxToast.showToast(it.errorMsg)
            }
        }

        mViewModel.verCodeResult.observe(viewLifecycleOwner) {
            dismissLoading()
            if (it.isSuccess) {
                RxToast.showToast("发送成功")
            } else {
                RxToast.showToast(it.errorMsg)
            }
            mDatabind.accountSignedPhoneCommit.isEnabled = true
            mDatabind.accountSignedPhoneCommit.setBackgroundResource(R.drawable.round_btn_blue5_bg)
        }

        mViewModel.bindPhoneResult.observe(viewLifecycleOwner) {
            dismissLoading()
            if (it.isSuccess) {
                RxToast.showToast("绑定成功")
                mViewModel.getUserMemberInfo()
            } else {
                RxToast.showToast(it.errorMsg)
            }
        }

        mViewModel.bindCardResult.observe(viewLifecycleOwner) { resultState ->
            dismissLoading()
            parseState(resultState, { it ->
                job = countDownCoroutines(60, {
                    mDatabind.accountVerifyCodeSendBank.text =
                        "(" + it + ")" + getString(R.string.mine_account_unbind_phone_activity_later_second_reload)
                    mDatabind.accountVerifyCodeSendBank.isClickable = false
                }, {
                    mDatabind.accountVerifyCodeSendBank.text = "获取验证码"
                    mDatabind.accountVerifyCodeSendBank.isClickable = true
                }, lifecycleScope)
                mTranceNum = it.tranceNum
                RxToast.showToast("发送成功")
            }, {
                RxToast.showToast(it.message)
            })
        }
        mViewModel.sureBindCardResult.observe(viewLifecycleOwner) {
            if (it.isSuccess) {
                RxToast.showToast("绑卡成功")
                if (mInToType == "mineBank") {
                    nav().navigateUp()
                } else {
                    nav().navigateAction(R.id.action_to_mine_banking, Bundle().apply {
                        putInt(Constant.INTO_TYPE, 2)//不是从首页跳入
                    })
                }
            } else {
                RxToast.showToast(it.errorMsg)
            }
        }
    }

    private fun changeBtnStatus(it: AccountUserInfo) {
        if (it.isIdentityChecked && it.isSignContract && it.isPhoneChecked && it.isBindBank && it.isSetPayPwd) {
            if (mInToType == "mineBank") {
                nav().navigateUp()
            } else {
                nav().navigateAction(R.id.action_to_mine_banking, Bundle().apply {
                    putInt(Constant.INTO_TYPE, 2)//从认证流程页跳入
                })
            }
            return
        }
        if (it.isIdentityChecked) {
            mDatabind.accountCheckSignContact.isClickable = true
            mDatabind.accountCheckSignContact.isEnabled = true
            mDatabind.accountCheckSignContact.setBackgroundResource(R.drawable.round_btn_blue5_bg)
        }
        if (it.isSignContract) {
            mDatabind.accountSignedPhoneCommit.isClickable = true
            mDatabind.accountSignedPhoneCommit.isEnabled = true
            mDatabind.accountVerifyCodeSend.isEnabled = true
            mDatabind.accountSignedPhoneCommit.setBackgroundResource(R.drawable.round_btn_blue5_bg)
        }
        if (it.isPhoneChecked) {
            mDatabind.accountCheckSetPwd.isClickable = true
            mDatabind.accountCheckSetPwd.isEnabled = true
            mDatabind.accountCheckSetPwd.setBackgroundResource(R.drawable.round_btn_blue5_bg)
        }
    }

    override fun onBindViewClick() {
        super.onBindViewClick()
        setOnclickNoRepeat(
            mDatabind.includeToolbarMenu.tvRightMenu,
            mDatabind.accountRealNameCommit,
            mDatabind.accountCheckSignContact,
            mDatabind.accountSignedPhoneCommit,
            mDatabind.accountVerifyCodeSend,
            mDatabind.accountSignedBankCardCommit,
            mDatabind.accountVerifyCodeSendBank,
            mDatabind.accountCheckSetPwd,
            mDatabind.ivProcessFront,
            mDatabind.ivProcessBack,
        ) {
            when (it) {
                mDatabind.ivProcessFront -> {
                    selectHeadIcon("front")
                    mIdCardType = "front"
                }

                mDatabind.ivProcessBack -> {
                    selectHeadIcon("back")
                    mIdCardType = "back"
                }

                mDatabind.includeToolbarMenu.tvRightMenu -> {
                    if (mInToType == "mineBank") {
                        nav().navigateUp()
                    } else {
                        nav().navigateAction(R.id.action_to_mine_banking, Bundle().apply {
                            putInt(Constant.INTO_TYPE, 2)
                        })
                    }
                }

                mDatabind.accountRealNameCommit -> {
                    setAccountRealName()
                }

                mDatabind.accountCheckSignContact -> {
                    nav().navigateAction(R.id.action_to_account_signing)
                }

                mDatabind.accountSignedPhoneCommit -> {
                    bindPhoneMethod()
                }

                mDatabind.accountVerifyCodeSend -> {
                    accountVerifyCodeSend()
                }

                mDatabind.accountVerifyCodeSendBank -> {
                    signedBankCard()
                }

                mDatabind.accountSignedBankCardCommit -> {
                    signedBankCardCommit()
                }

                mDatabind.accountCheckSetPwd -> {//设置支付密码
                    nav().navigateAction(R.id.action_to_fragment_set_payment_pwd, Bundle().apply {
                        putInt("type", 1)//设置密码
                    })
                }
            }
        }
    }

    private fun selectHeadIcon(type: String) {
        val selectionModel: PictureSelectionModel = PictureSelector.create(context)
            .openGallery(SelectMimeType.ofImage())
            .setSelectorUIStyle(PictureSelectorStyle())
            .setImageEngine(GlideEngine.createGlideEngine())
            .setCompressEngine(PictureUtil.getCompressFileEngine())
//            .setCropEngine(PictureUtil.getCropFileEngine())//图片剪裁
            .setSandboxFileEngine(MeSandboxFileEngine())
            .setSelectionMode(SelectModeConfig.SINGLE)
            .setCameraInterceptListener(PictureUtil.getCustomCameraEvent())
            .setPermissionDescriptionListener(PictureUtil.getPermissionDescriptionListener())
            .setPreviewInterceptListener(PictureUtil.getPreviewInterceptListener())
            .setPermissionDeniedListener(PictureUtil.getPermissionDeniedListener())
            .setQueryFilterListener { false }
            .isLoopAutoVideoPlay(false)
            .isPageSyncAlbumCount(true)
            .setLanguage(LanguageConfig.SYSTEM_LANGUAGE)
            .setQuerySortOrder("")
            .isDisplayCamera(true)
            .isOpenClickSound(false)
            .isPreviewImage(true)
            .isMaxSelectEnabledMask(true)
            .isDirectReturnSingle(true)
        selectionModel.forResult(object : OnResultCallbackListener<LocalMedia> {
            override fun onResult(result: ArrayList<LocalMedia>?) {
                val path = result!![0].realPath//获取压缩后的路径
                val file = File(path)
                val bitmap = BitmapFactory.decodeFile(path)
                if (type == "front") {
                    idCardFrontFile = file
                    compressedPicture(path, "front")//先对图片进行压缩处理
                    mDatabind.ivProcessFront.setImageBitmap(bitmap)
                } else {
                    idCardBackFile = file
                    compressedPicture(path, "front")
                    mDatabind.ivProcessBack.setImageBitmap(bitmap)
                }
            }

            override fun onCancel() {}
        })

    }

    private fun compressedPicture(pathUrl: String, type: String) {
        /** 把单张图片压缩到1024k以内 同时像素不超过1200（宽、高都不大于1200） */
        EasyImgCompress.withSinglePic(context, pathUrl)
            .maxPx(1200)
            .maxSize(1024)
            .enableLog(true)
            .setOnCompressSinglePicListener(object : OnCompressSinglePicListener {
                override fun onStart() {}
                override fun onSuccess(file: File) {
                    if (type == "front") {
                        idCardFrontFile = file
                    } else {
                        idCardBackFile = file
                    }
                    idCard(file.path, type)
                }

                override fun onError(error: String) {}
            }).start()
    }

    private fun idCard(path: String?, type: String) {
        runOnUiThread {
            showLoading("识别中...")
        }
        Thread {
            val mediaType: MediaType = "application/x-www-form-urlencoded".toMediaTypeOrNull()!!
            // image 可以通过 getFileContentAsBase64("C:\fakepath\微信图片_20230809113403.jpg") 方法获取,如果Content-Type是application/x-www-form-urlencoded时,第二个参数传true
            val body = ("id_card_side=$mIdCardType&image=" + URLEncoder.encode(
                Base64Util.encode(FileUtil.readFileByBytes(path)), "UTF-8"
            ) + "&url=https%3A%2F%2Faip.baidubce.com%2Frest%2F2.0%2Focr%2Fv1%2Fidcard&detect_risk=false&detect_quality=false&detect_photo=false&detect_card=false&detect_direction=false"
                    ).toRequestBody(mediaType)
            val request = Request.Builder()
                .url("https://aip.baidubce.com/rest/2.0/ocr/v1/idcard?access_token=" + getAccessToken())//Constant.ACCESS_TOKEN
                .method("POST", body)
                .addHeader("Content-Type", "application/x-www-form-urlencoded")
                .addHeader("Accept", "application/json")
                .build()
            val response = HTTP_CLIENT.newCall(request).execute()
            runOnUiThread {
                dismissLoading()
            }
            setCardInfo(response.body?.string(), type)
        }.start()
    }

    @Throws(IOException::class)
    private fun getAccessToken(): String? {
        val mediaType = "application/x-www-form-urlencoded".toMediaTypeOrNull()
        val body = RequestBody.create(
            mediaType, "grant_type=client_credentials&client_id=" + Constant.API_KEY
                    + "&client_secret=" + Constant.SECRET_KEY
        )
        val request: Request = Request.Builder()
            .url("https://aip.baidubce.com/oauth/2.0/token")
            .method("POST", body)
            .addHeader("Content-Type", "application/x-www-form-urlencoded")
            .build()
        val response = HTTP_CLIENT.newCall(request).execute()
        return JSONObject(response.body!!.string()).getString("access_token")
    }

    private fun setCardInfo(data: String?, type: String) {
        try {
            LogUtils.debugInfo(data)
            runOnUiThread {
                if (JSONObject(data.toString()).has("error_code")) {
                    if (JSONObject(data.toString()).getInt("error_code") == 111) {
                        RxToast.showToast("令牌过期")
                        return@runOnUiThread
                    }
                }
                if (type == "back") {
                    if (JSONObject(data.toString()).has("idcard_number_type")) {
                        idCardNumberTypeBack = JSONObject(data.toString()).getInt("idcard_number_type")
                        if (idCardNumberTypeBack == -1) {
                            RxToast.showToast("识别失败，请重新上传")
                            return@runOnUiThread
                        }
                    }
                    idCardNumberTypeBack = 1
                    val currentDate = DatetimeUtil.getTimeStringYear()
                    val wordResultBack = data?.let { JSONObject(it).getJSONObject("words_result") }
                    if (wordResultBack != null) {
                        if (wordResultBack.has("失效日期")) {
                            val date = wordResultBack.getJSONObject("失效日期")
                            val wordsDate = date.getString("words")
                            if (currentDate.isNotEmpty() && wordsDate.isNotEmpty()) {
                                if (wordsDate != "长期") {
                                    if (currentDate.toInt() > wordsDate.toInt()) {
                                        RxToast.showToast("证件已过期，请上传有效证件")
                                    }
                                }
                            }
                        }
                    }
                } else {
                    if (JSONObject(data.toString()).has("idcard_number_type")) {
                        idCardNumberTypeFront = JSONObject(data.toString()).getInt("idcard_number_type")
                        if (idCardNumberTypeFront == -1) {
                            RxToast.showToast("识别失败，请重新上传")
                            mDatabind.accountRealName.setText("")
                            mDatabind.accountRealNameIdCard.setText("")
                            return@runOnUiThread
                        }
                    }
                    idCardNumberTypeFront = 1
                    val name: JSONObject?
                    val idCardNum: JSONObject?
                    val wordResult = data?.let { JSONObject(it).getJSONObject("words_result") }
                    if (wordResult != null) {
                        if (wordResult.has("姓名")) {
                            name = wordResult.getJSONObject("姓名")
                            if (name != null) {
                                val wordName = name.getString("words")
                                mDatabind.accountRealName.setText(wordName)
                            }
                        }
                        if (wordResult.has("公民身份号码")) {
                            idCardNum = wordResult.getJSONObject("公民身份号码")
                            if (idCardNum != null) {
                                val wordIdNUm = idCardNum.getString("words")
                                mDatabind.accountRealNameIdCard.setText(wordIdNUm)
                            }
                        }
                    }
                }
            }
        } catch (e: Exception) {
            e.printStackTrace()
        }
    }

    private fun signedBankCardCommit() {
        when {
            mDatabind.accountIdCardBank.text?.isEmpty() == true -> showMessage("请输入银行卡号")
            mDatabind.accountPhoneBank.text?.isEmpty() == true -> showMessage(resources.getString(R.string.user_mobile_number))
            !Util.isTelPhoneNumber(mDatabind.accountPhoneBank.text.toString()) -> showMessage(
                resources.getString(
                    R.string.user_phone_number_wrong
                )
            )

            mDatabind.accountVerifyCodeBank.text?.isEmpty() == true -> showMessage(
                resources.getString(
                    R.string.user_verification_code
                )
            )

            else -> {
                val body = SureBindCardParam(
                    verificationCode = mDatabind.accountVerifyCodeBank.text.toString(),
                    phone = mDatabind.accountPhoneBank.text.toString(),
                    tranceNum = mTranceNum
                )
                showLoading(getString(R.string.loading))
                mViewModel.bindBankCard(body)
            }
        }
    }

    @SuppressLint("SetTextI18n")
    private fun signedBankCard() {
        when {
            mDatabind.accountIdCardBank.text?.isEmpty() == true -> showMessage("请输入银行卡号")
            mDatabind.accountPhoneBank.text?.isEmpty() == true -> showMessage(resources.getString(R.string.user_mobile_number))
            !Util.isTelPhoneNumber(mDatabind.accountPhoneBank.text.toString()) -> showMessage(
                resources.getString(
                    R.string.user_phone_number_wrong
                )
            )

            else -> {
                val body = ApplyBindCardParam(
                    carNo = mDatabind.accountIdCardBank.text.toString(),
                    phone = mDatabind.accountPhoneBank.text.toString()
                )
                showLoading(getString(R.string.loading))
                mViewModel.applyBindBankCardV2(body)
            }
        }
    }

    @SuppressLint("SetTextI18n")
    private fun accountVerifyCodeSend() {
        when {
            mDatabind.accountBindPhoneNumber.text?.isEmpty() == true -> showMessage(
                resources.getString(
                    R.string.user_mobile_number
                )
            )

            !Util.isTelPhoneNumber(mDatabind.accountBindPhoneNumber.text.toString()) -> showMessage(
                resources.getString(
                    R.string.user_phone_number_wrong
                )
            )

            else -> {
                job = countDownCoroutines(60, {
                    mDatabind.accountVerifyCodeSend.text = "(" + it + ")" + getString(R.string.mine_account_unbind_phone_activity_later_second_reload)
                    mDatabind.accountVerifyCodeSend.isEnabled = false
                }, {
                    mDatabind.accountVerifyCodeSend.text = "获取验证码"
                    mDatabind.accountVerifyCodeSend.isEnabled = true
                }, lifecycleScope)
                val paramsBody = AccountBindPhoneParam(
                    type = 9,
                    phone = mDatabind.accountBindPhoneNumber.text.toString()
                )
                showLoading(getString(R.string.loading))
                mViewModel.sendVerificationCode(paramsBody)
            }
        }
    }

    private fun bindPhoneMethod() {
        when {
            mDatabind.accountBindPhoneNumber.text?.isEmpty() == true -> showMessage(
                resources.getString(
                    R.string.user_mobile_number
                )
            )

            !Util.isTelPhoneNumber(mDatabind.accountBindPhoneNumber.text.toString()) -> showMessage(
                resources.getString(
                    R.string.user_phone_number_wrong
                )
            )

            mDatabind.accountBindPhoneVerifyCode.text?.isEmpty() == true -> showMessage(
                resources.getString(
                    R.string.user_verification_code
                )
            )

            else -> {
                val body = AccountBindPhoneBean(
                    verificationCode = mDatabind.accountBindPhoneVerifyCode.text.toString(),
                    phone = mDatabind.accountBindPhoneNumber.text.toString()
                )
                showLoading(getString(R.string.loading))
                mViewModel.bindPhone(body)
            }
        }
    }

    private fun setAccountRealName() {
        if (idCardFrontFile == null || idCardBackFile == null) {
            RxToast.warning("请上传身份证正面和反面照")
            return
        }
        LogUtils.debugInfo("onSuccess size = " + GBMBKBUtil.getSize(idCardFrontFile!!.length()) + " getAbsolutePath= " + idCardBackFile!!.absolutePath)
        when {
            idCardNumberTypeFront == -1 || idCardNumberTypeBack == -1 -> showMessage("请上传有效身份证件")
            !Util.isIdNO(context, mDatabind.accountRealNameIdCard.text.toString()) -> showMessage(
                resources.getString(
                    R.string.user_id_number_wrong
                )
            )

            else -> {
                val body = AccountRealNameParams(
                    name = mDatabind.accountRealName.text.toString(),
                    identityNo = mDatabind.accountRealNameIdCard.text.toString(),
                    idCardFront = idCardFrontFile,
                    idCardBack = idCardBackFile,
                )
                showLoading(getString(R.string.loading))
                mViewModel.setRealName(body)
            }
        }
    }
}